#include "Nodo.h"

int Rectangle::read(TiXmlElement *shape)
{
	float ax1;
	float ax2;
	float ay1;
	float ay2;
	
	if (shape->QueryFloatAttribute("x1",&ax1)==TIXML_SUCCESS &&
		shape->QueryFloatAttribute("x2",&ax2)==TIXML_SUCCESS&&
		shape->QueryFloatAttribute("y1",&ay1)==TIXML_SUCCESS&&
		shape->QueryFloatAttribute("y2",&ay2)==TIXML_SUCCESS)
	{
		x1=ax1;
		x2=ax2;
		y1=ay1;
		y2=ay2;
		return 0;
	}
	else return -1;
	
}

void Rectangle::draw()
{
	
	//aplicacao ou nao de textura
	GLboolean texture_state;
	glGetBooleanv(GL_TEXTURE_2D,&texture_state);
	if(node_texture->first==-2) glDisable(GL_TEXTURE_2D);
	else if(node_texture->first!=0)
	{
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, node_texture->first);
		Nodo::texture_s=node_texture->second.first;
		Nodo::texture_t=node_texture->second.second;
	}

	//aplicacao ou nao de material
	GLfloat ashininess[1];
	GLfloat aspecular[4];
	GLfloat adiffuse[4];
	GLfloat aambient[4];
	GLfloat aemission[4];
	glGetMaterialfv(GL_FRONT,GL_SHININESS,ashininess);
	glGetMaterialfv(GL_FRONT,GL_SPECULAR,aspecular);
	glGetMaterialfv(GL_FRONT,GL_DIFFUSE,adiffuse);
	glGetMaterialfv(GL_FRONT,GL_AMBIENT,aambient);
	glGetMaterialfv(GL_FRONT,GL_EMISSION,aemission);
	if(materials[active_material]->shininess[0]>-5)materials[active_material]->make();

	glBegin(GL_TRIANGLE_FAN);
	glTexCoord2f(0.0,0.0); glVertex3f(x1,y1,0.0);
	glTexCoord2f((x2-x1)/Nodo::texture_s,0.0); glVertex3f(x2,y1,0.0);
	glTexCoord2f((x2-x1)/Nodo::texture_s,(y2-y1)/Nodo::texture_t); glVertex3f(x2,y2,0.0);
	glTexCoord2f(0.0,(y2-y1)/Nodo::texture_t); glVertex3f(x1,y2,0.0);
	glEnd();
	
	//reposicao dos valores de materiais, texturas e transformacoes
	if(texture_state)glEnable(GL_TEXTURE_2D);
	else glDisable(GL_TEXTURE_2D);
	glMaterialfv(GL_FRONT,GL_SHININESS,ashininess);
	glMaterialfv(GL_FRONT,GL_SPECULAR,aspecular);
	glMaterialfv(GL_FRONT,GL_DIFFUSE,adiffuse);
	glMaterialfv(GL_FRONT,GL_AMBIENT,aambient);
	glMaterialfv(GL_FRONT,GL_EMISSION,aemission);
}

int Sphere::read(TiXmlElement *shape)
{
	float aradius;
	float aslices;
	float astacks;
	
	if (shape->QueryFloatAttribute("radius",&aradius)==TIXML_SUCCESS &&
		shape->QueryFloatAttribute("slices",&aslices)==TIXML_SUCCESS&&
		shape->QueryFloatAttribute("stacks",&astacks)==TIXML_SUCCESS)
		
	{
		radius=aradius;
		slices=aslices;
		stacks=astacks;
		return 0;
	}
	else return -1;

}
void Sphere::draw()
{
	GLUquadric* glQ=gluNewQuadric();

	//aplicacao ou nao de textura
	GLboolean texture_state;
	glGetBooleanv(GL_TEXTURE_2D,&texture_state);
	if(node_texture->first==-2) glDisable(GL_TEXTURE_2D);
	else if(node_texture->first!=0)
	{
		glEnable(GL_TEXTURE_2D);
		gluQuadricTexture(glQ,node_texture->first);
	}
	else
	{
		int textureN;
		glGetIntegerv(GL_TEXTURE_BINDING_2D,&textureN);
		gluQuadricTexture(glQ,textureN);
	}

	//aplicacao ou nao de material
	GLfloat ashininess[1];
	GLfloat aspecular[4];
	GLfloat adiffuse[4];
	GLfloat aambient[4];
	GLfloat aemission[4];
	glGetMaterialfv(GL_FRONT,GL_SHININESS,ashininess);
	glGetMaterialfv(GL_FRONT,GL_SPECULAR,aspecular);
	glGetMaterialfv(GL_FRONT,GL_DIFFUSE,adiffuse);
	glGetMaterialfv(GL_FRONT,GL_AMBIENT,aambient);
	glGetMaterialfv(GL_FRONT,GL_EMISSION,aemission);
	if(materials[active_material]->shininess[0]>-5)materials[active_material]->make();

	gluSphere(glQ,radius,slices,stacks);

	//reposicao dos valores de materiais, texturas e transformacoes
	if(texture_state)glEnable(GL_TEXTURE_2D);
	else glDisable(GL_TEXTURE_2D);
	glMaterialfv(GL_FRONT,GL_SHININESS,ashininess);
	glMaterialfv(GL_FRONT,GL_SPECULAR,aspecular);
	glMaterialfv(GL_FRONT,GL_DIFFUSE,adiffuse);
	glMaterialfv(GL_FRONT,GL_AMBIENT,aambient);
	glMaterialfv(GL_FRONT,GL_EMISSION,aemission);
}


int Triangle::read(TiXmlElement *shape)
{
	float ax1;
	float ax2;
	float ax3;
	float ay1;
	float ay2;
	float ay3;
	float az1;
	float az2;
	float az3;
	
	if (shape->QueryFloatAttribute("x1",&ax1)==TIXML_SUCCESS&&
		shape->QueryFloatAttribute("x2",&ax2)==TIXML_SUCCESS&&
		shape->QueryFloatAttribute("x3",&ax3)==TIXML_SUCCESS&&
		shape->QueryFloatAttribute("y1",&ay1)==TIXML_SUCCESS&&
		shape->QueryFloatAttribute("y2",&ay2)==TIXML_SUCCESS&&
		shape->QueryFloatAttribute("y3",&ay3)==TIXML_SUCCESS&&
		shape->QueryFloatAttribute("z1",&az1)==TIXML_SUCCESS&&
		shape->QueryFloatAttribute("z2",&az2)==TIXML_SUCCESS&&
		shape->QueryFloatAttribute("z3",&az3)==TIXML_SUCCESS)
	{
		x1=ax1;
		x2=ax2;
		x3=ax3;
		y1=ay1;
		y2=ay2;
		y3=ay3;
		z1=az1;
		z2=az2;
		z3=az3;
		return 0;
	}
	else return -1;
	
}
void Triangle::draw()
{
	//aplicacao ou nao de textura
	GLboolean texture_state;
	glGetBooleanv(GL_TEXTURE_2D,&texture_state);
	if(node_texture->first==-2) glDisable(GL_TEXTURE_2D);
	else if(node_texture->first!=0)
	{
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, node_texture->first);
		Nodo::texture_s=node_texture->second.first;
		Nodo::texture_t=node_texture->second.second;
	}

	//aplicacao ou nao de material
	GLfloat ashininess[1];
	GLfloat aspecular[4];
	GLfloat adiffuse[4];
	GLfloat aambient[4];
	GLfloat aemission[4];
	glGetMaterialfv(GL_FRONT,GL_SHININESS,ashininess);
	glGetMaterialfv(GL_FRONT,GL_SPECULAR,aspecular);
	glGetMaterialfv(GL_FRONT,GL_DIFFUSE,adiffuse);
	glGetMaterialfv(GL_FRONT,GL_AMBIENT,aambient);
	glGetMaterialfv(GL_FRONT,GL_EMISSION,aemission);
	if(materials[active_material]->shininess[0]>-5)materials[active_material]->make();


	glBegin(GL_TRIANGLES);
		glTexCoord2f(0.0,0.0);glVertex3f(x1,y1,z1);              
		glTexCoord2f((x2-x1)/Nodo::texture_s,0.0);glVertex3f(x2,y2,z2);              
		glTexCoord2f((x2-x1)/Nodo::texture_s,(y2-y1)/Nodo::texture_t);glVertex3f(x3,y3,z3);
	glEnd(); 

	//reposicao dos valores de materiais, texturas e transformacoes
	if(texture_state)glEnable(GL_TEXTURE_2D);
	else glDisable(GL_TEXTURE_2D);
	glMaterialfv(GL_FRONT,GL_SHININESS,ashininess);
	glMaterialfv(GL_FRONT,GL_SPECULAR,aspecular);
	glMaterialfv(GL_FRONT,GL_DIFFUSE,adiffuse);
	glMaterialfv(GL_FRONT,GL_AMBIENT,aambient);
	glMaterialfv(GL_FRONT,GL_EMISSION,aemission);
}

int Torus::read(TiXmlElement *shape)
{
	float ainner;
	float aouter;
	float aslices;
	float aloops;
	
	if (shape->QueryFloatAttribute("inner",&ainner)==TIXML_SUCCESS &&
		shape->QueryFloatAttribute("outer",&aouter)==TIXML_SUCCESS&&
		shape->QueryFloatAttribute("slices",&aslices)==TIXML_SUCCESS&&
		shape->QueryFloatAttribute("loops",&aloops)==TIXML_SUCCESS)
		
	{
		inner=ainner;
		outer=aouter;
		slices=aslices;
		loops=aloops;
		return 0;
	}
	else return -1;
}
void Torus::draw()
{
	GLUquadric* glQ=gluNewQuadric();

	//aplicacao ou nao de textura
	GLboolean texture_state;
	glGetBooleanv(GL_TEXTURE_2D,&texture_state);
	if(node_texture->first==-2) glDisable(GL_TEXTURE_2D);
	else if(node_texture->first!=0)
	{
		glEnable(GL_TEXTURE_2D);
		gluQuadricTexture(glQ,node_texture->first);
	}
	else
	{
		int textureN;
		glGetIntegerv(GL_TEXTURE_BINDING_2D,&textureN);
		gluQuadricTexture(glQ,textureN);
	}

	//aplicacao ou nao de material
	GLfloat ashininess[1];
	GLfloat aspecular[4];
	GLfloat adiffuse[4];
	GLfloat aambient[4];
	GLfloat aemission[4];
	glGetMaterialfv(GL_FRONT,GL_SHININESS,ashininess);
	glGetMaterialfv(GL_FRONT,GL_SPECULAR,aspecular);
	glGetMaterialfv(GL_FRONT,GL_DIFFUSE,adiffuse);
	glGetMaterialfv(GL_FRONT,GL_AMBIENT,aambient);
	glGetMaterialfv(GL_FRONT,GL_EMISSION,aemission);
	if(materials[active_material]->shininess[0]>-5)materials[active_material]->make();
	//cout<<"UM TORUS\n";
	glutSolidTorus(inner,outer,slices,loops);
	//reposicao dos valores de materiais, texturas e transformacoes
	if(texture_state)glEnable(GL_TEXTURE_2D);
	else glDisable(GL_TEXTURE_2D);
	glMaterialfv(GL_FRONT,GL_SHININESS,ashininess);
	glMaterialfv(GL_FRONT,GL_SPECULAR,aspecular);
	glMaterialfv(GL_FRONT,GL_DIFFUSE,adiffuse);
	glMaterialfv(GL_FRONT,GL_AMBIENT,aambient);
	glMaterialfv(GL_FRONT,GL_EMISSION,aemission);
}

int Cylinder::read(TiXmlElement *shape)
{
	float abase;
	float atop;
	float aheight;
	float aslices;
	float astacks;
	
	if (shape->QueryFloatAttribute("top",&atop)==TIXML_SUCCESS &&
		shape->QueryFloatAttribute("base",&abase)==TIXML_SUCCESS&&
		shape->QueryFloatAttribute("height",&aheight)==TIXML_SUCCESS&&
		shape->QueryFloatAttribute("slices",&aslices)==TIXML_SUCCESS&&
		shape->QueryFloatAttribute("stacks",&astacks)==TIXML_SUCCESS)
	{
		base = abase;
		top = atop;
		height = aheight;
		slices = aslices;
		stacks = astacks;
		return 0;
	}
	else return -1;
}
void Cylinder::draw()
{
	GLUquadric* glQ=gluNewQuadric();

	//aplicacao ou nao de textura
	GLboolean texture_state;
	glGetBooleanv(GL_TEXTURE_2D,&texture_state);
	if(node_texture->first==-2) glDisable(GL_TEXTURE_2D);
	else if(node_texture->first!=0)
	{
		glEnable(GL_TEXTURE_2D);
		gluQuadricTexture(glQ,node_texture->first);
	}
	else
	{
		int textureN;
		glGetIntegerv(GL_TEXTURE_BINDING_2D,&textureN);
		gluQuadricTexture(glQ,textureN);
	}

	//aplicacao ou nao de material
	GLfloat ashininess[1];
	GLfloat aspecular[4];
	GLfloat adiffuse[4];
	GLfloat aambient[4];
	GLfloat aemission[4];
	glGetMaterialfv(GL_FRONT,GL_SHININESS,ashininess);
	glGetMaterialfv(GL_FRONT,GL_SPECULAR,aspecular);
	glGetMaterialfv(GL_FRONT,GL_DIFFUSE,adiffuse);
	glGetMaterialfv(GL_FRONT,GL_AMBIENT,aambient);
	glGetMaterialfv(GL_FRONT,GL_EMISSION,aemission);
	if(materials[active_material]->shininess[0]>-5)materials[active_material]->make();

	
	glPushMatrix();
	glRotatef(180,0,1,0);
	gluDisk(glQ,0,base,slices,stacks);
	glPopMatrix();

	glPushMatrix();
	glTranslatef(0,0,height);
	gluDisk(glQ,0,top,slices,stacks);
	glPopMatrix();

	gluCylinder(glQ,base,top,height,slices,stacks);

	//reposicao dos valores de materiais, texturas e transformacoes
	if(texture_state)glEnable(GL_TEXTURE_2D);
	else glDisable(GL_TEXTURE_2D);
	glMaterialfv(GL_FRONT,GL_SHININESS,ashininess);
	glMaterialfv(GL_FRONT,GL_SPECULAR,aspecular);
	glMaterialfv(GL_FRONT,GL_DIFFUSE,adiffuse);
	glMaterialfv(GL_FRONT,GL_AMBIENT,aambient);
	glMaterialfv(GL_FRONT,GL_EMISSION,aemission);
}

void Component::draw()
{
	glPushMatrix();
	//fazer transformacao geometrica
	transf->make();
	
	//aplicacao ou nao de textura
	GLboolean texture_state;
	glGetBooleanv(GL_TEXTURE_2D,&texture_state);
	if(node_texture->first==-2) glDisable(GL_TEXTURE_2D);
	else if(node_texture->first!=0)
	{
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, node_texture->first);
		Nodo::texture_s=node_texture->second.first;
		Nodo::texture_t=node_texture->second.second;
	}

	//aplicacao ou nao de material
	GLfloat ashininess[1];
	GLfloat aspecular[4];
	GLfloat adiffuse[4];
	GLfloat aambient[4];
	GLfloat aemission[4];
	glGetMaterialfv(GL_FRONT,GL_SHININESS,ashininess);
	glGetMaterialfv(GL_FRONT,GL_SPECULAR,aspecular);
	glGetMaterialfv(GL_FRONT,GL_DIFFUSE,adiffuse);
	glGetMaterialfv(GL_FRONT,GL_AMBIENT,aambient);
	glGetMaterialfv(GL_FRONT,GL_EMISSION,aemission);
	if(materials[active_material]->shininess[0]>-5)materials[active_material]->make();
	
	//percorrer todos os filhos
	//cout<<"SOU O:"<<this->getID()<<endl;
	for(int i=0;i<sons.size();i++)
	{
		//cout<<"A DESENHAR O FILHO:"<<sons[i]->getID()<<endl;
		sons[i]->draw();
		glBindTexture(GL_TEXTURE_2D, node_texture->first);

	}

	//reposicao dos valores de materiais, texturas e transformacoes
	if(texture_state)glEnable(GL_TEXTURE_2D);
	else glDisable(GL_TEXTURE_2D);
	glPopMatrix();
	glMaterialfv(GL_FRONT,GL_SHININESS,ashininess);
	glMaterialfv(GL_FRONT,GL_SPECULAR,aspecular);
	glMaterialfv(GL_FRONT,GL_DIFFUSE,adiffuse);
	glMaterialfv(GL_FRONT,GL_AMBIENT,aambient);
	glMaterialfv(GL_FRONT,GL_EMISSION,aemission);
}